<?php
abstract class App_Model_Mapper_Abstract 
{
 
    /**
     * Database adapter
     *
     * @var Zend_Db_Adapter_Abstract
     */
    protected $_adapter;
 
    /**
     * Default database adapter
     *
     * @var Zend_Db_Adapter_Abstract
     */
    protected static $_defaultAdapter;
 
    /**
     * Table name
     *
     * @var string
     */
    protected $_name;
    
    /*
     * values map array
     */
    protected $_map; 
    
    protected $_entityClassName;
    
    /**
     * Constructor
     *
     * This method is final, because it should not be used to initialize, use
     * {@link _init()} instead
     *
     * @param Zend_Db_Adapter_Abstract $adapter
     *
     * @throws Firal_Model_Mapper_RuntimeException If there is no adapter defined
     *
     * @return void
     */

    final public function __construct(Zend_Db_Adapter_Abstract $adapter = null)
    {
        if (null === $adapter) {
            if (null === ($adapter = self::getDefaultAdapter())) {
               // throw new Firal_Model_Mapper_RuntimeException('There was no adapter defined');
            }
        }
        $this->_adapter = $adapter;
        
        $this->_init();
    }
 
    /**
     * Init hook
     *
     * @return void
     */
    protected function _init()
    {}
 
    /**
     * Get the database adapter
     *
     * @return Zend_Db_Adapter_Abstract
     */
    public function getAdapter()
    {
        return $this->_adapter;
    }
 
    /**
     * Get the table name
     *
     * @return string
     */
    public function getTableName()
    {
        return $this->_name;
    }
 
    // static functions
 
    /**
     * Set the default database adapter
     *
     * @param Zend_Db_Adapter_Abstract $adapter
     *
     * @return void
     */
    public static function setDefaultAdapter(Zend_Db_Adapter_Abstract $adapter)
    {
        self::$_defaultAdapter = $adapter;
    }
 
    /**
     * Get the default database adapter
     *
     * @return Zend_Db_Adapter_Abstract
     */
    public static function getDefaultAdapter()
    {
        return self::$_defaultAdapter;
    }
    /*
     * set map loader
     */
    public function setMapLoader($loader)
    {
        $this->_loader = $loader;
    }
    
    /*
     * Get map loader
     */
    public function getMapLoader()
    {
        return $this->_loader;
    }
    
    /*
     * Get Map Array
     */
    public function getMap()
    {
        return $this->_loader->getMap();
        
    }
    
    /*
     * Set Map array
     */
    public function setMap(array $map)
    {
        $this->_map = $map;
    }
    
    /*
     * save entity
     */
    public function save($entity)
    {
        $data = array();
        foreach($this->_map as $key => $value){
            if($entity->$key !== null){            
                $data[$value] = $entity->{$key}; 
            }
        }
        if($data['id'] === null){
              $this->getAdapter()->insert($this->_name, $data);
              $data['id'] = $this->getAdapter()->lastInsertId($this->_name);
        } else {
            $this->_adapter->update(
                $this->_name, 
                $data,
                $this->getAdapter()->quoteInto('id=?', $data['id'])
            );
        }
        return $this->initEntity($data);
    }
    
    public function initEntity($data)
    {
        $entity = new $this->_entityClassName();
        foreach($this->_map as $key => $value){
            $entity->{$key} = $data[$value];
        }
        return $entity;
    }
    
    public function load($id)
    {
        $select = $this->_adapter->select()->from($this->_name)
            ->where('id = ' . (integer) $id)->limit(1);
        $rowset = $this->_adapter->fetchAll($select);
        return $this->initEntity($rowset[0]);
    }
    
    public function getAll()
    {
        $select = $this->_adapter->select()->from($this->_name);
        $result = $this->_adapter->fetchAll($select);
        $entitys = array();
        foreach($result as $data){
            $entitys[] = $this->initEntity($data);
        }
        return $entitys;
    }
    
    public function delete($entity)
    {
        if(!$entity->id){
            return false;
        }
        $this->_adapter->delete($this->_name, 'id = ' . $entity->id);
    }
    
    public function getEntityClassName()
    {
        return $this->_entityClassName;
    }
    
    abstract public function getContent($page, array $options = null);
}